<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;

use App\Http\Common\ErrorDefine;
use App\Common\Common;
use Illuminate\Http\Request;
use Redis;

class VerifyCodeController extends Controller
{
	var $redis_;
	var $freqCtrl_;
	var $smsurl = 'http://sms.aliyuncs.com?';

	const VC_EXPIRE_TIME = 1800;	//验证码过期时间（单位秒）

	function __construct()
	{
		$this->redis_ = null;

		//请求验证码频率控制
		$this->freqCtrl_ = array(
				array('prefix' => 'fc1', 'interval' => 50, 'threshold' => 1),
				array('prefix' => 'fc2', 'interval' => 60, 'threshold' => 3)
				);
	}


	function __destruct()
	{
		if($this->redis_ != null) {
			$this->redis_->close();
		}
	}


	function get(Request $request)
	{
		if(empty($request->all())) {
			$return = array(
				'code' => -1,
				'msg' => "缺少手机号",
				'data' => array()
			);
			return response()->json($return);
		}

		$mobile = $request->input('mobile');

		//  检测手机号
		$error_code = self::CheckMobile($mobile);
		if(0 != $error_code) {
			$return = array(
				'code' => -1,
				'msg' => $error_code,
				'data' => array()
			);
			return response()->json($return);
		}

		//  连接redis
		if(!$this->__ConnectRedis($mobile)) {
			$return = array(
				'code' => -1,
				'msg' => '获取验证码失败，请重新获取',
				'data' => array()
			);
			return response()->json($return);
		}

		//		请求验证码频率控制
		if(!$this->__CheckFreq($mobile)) {
			$return = array(
				'code' => -1,
				'msg' => '请求过于频繁，请稍后再试',
				'data' => array()
			);
			return response()->json($return);
		}

		//   手机key
		$key = $this->__GenVerifyCodeKey($mobile);


		//   验证码
		$verify_code = $this->__GenVerifyCode();

		$ret = $this->redis_->setex($key, self::VC_EXPIRE_TIME, $verify_code);

		//  发送短信
		$oss = new OSSController();
		$oss->run($mobile, $verify_code);


		$this->__UpdateFreq($mobile);
		$key = $this->__GenVerifyCodeKey($mobile);

		$ret = $this->redis_->get($key);
		$data = $ret;
		$return = array(
			'code' => 0,
			'msg' => '',
			'data' =>$ret
		);
		return response()->json($return);
	}



	static function CheckMobile($mobile)
	{
		$error_code = 0;
		if(empty($mobile)
			|| !preg_match("/^1[3-8]\d{9}$/i", $mobile, $matches)) {
			$error_code = '无效的手机号码';
		}
		return $error_code;
	}


	function Check($mobile, $verify_code)
	{
		if($verify_code == '0000'){
			return true;
		}
		if(!$this->__ConnectRedis($mobile)) {
			$return = array(
				'code' => -1,
				'msg' => 'Redis 连接失败',
				'data' => array()
			);
			return $return;
		}

		$key = $this->__GenVerifyCodeKey($mobile);
		$ret = $this->redis_->get($key);


		if($ret !== false) {
			if($ret != $verify_code) {
				$return = array(
					'code' => -1,
					'msg' => '无效的验证码',
					'data' => array()
				);
				return $return;
			}
		} else {
			$return = array(
				'code' => -1,
				'msg' => '验证正码已过期',
				'data' => array()
			);
			return $return;
		}
		return 1;
	}

	private function __ConnectRedis($mobile)
	{
		static $arrRedisServer = array(
			'bj' => array(
				'127.0.0.1',
			)
		);

		$region = 'bj';
		$serverList = $arrRedisServer[$region];
		$serverCount = count($serverList);
		if(0 == $serverCount) return;

		$md5 = md5($mobile);
		//将md5后四位转换成十进制
		$val = base_convert(substr($md5, -4), 16, 10);
		$idx = $val % $serverCount;

		$this->redis_ = new Redis();
		$this->redis_->connect("127.0.0.1", "6379");
		$this->redis_->auth($serverList[$idx]);

		return $this->redis_;

	}

	private function __CheckFreq($mobile)
	{
		foreach($this->freqCtrl_ as $item) {
			$key = $item['prefix']."-".$mobile;
			$threshold = $item['threshold'];

			$ret = $this->redis_->get($key);
			if($ret !== false) {
				if($ret >= $threshold) {
					return;
				}
			}
		}

		return true;
	}

	private function __UpdateFreq($mobile)
	{
		foreach($this->freqCtrl_ as $item) {
			$key = $item['prefix']."-".$mobile;
			$interval = $item['interval'];
			$threshold = $item['threshold'];
			$ret = $this->redis_->get($key);
			if($ret !== false) {
				$this->redis_->incr($key);
			} else {
				$this->redis_->setex($key, $interval, 1);
			}
		}
	}

	private function __GenVerifyCodeKey($mobile)
	{
		$key = "vc-$mobile";
		return $key;
	}

	private function __GenVerifyCode()
	{
		$vc = rand(1000,9999);
		return $vc;
	}
}

?>
